/**
* 文档: https://www.quanzhan.co/luch-request/
* github: https://github.com/lei-mu/luch-request
* DCloud: http://ext.dcloud.net.cn/plugin?id=392
*/
import Request from 'luch-request';

const http = new Request();

/**
* 全局默认配置
* @param {Object} config 发送请求的配置数据
*/
http.setConfig(config => {
  config.baseURL = feConfig.api.base; // 根路径
  config.header = { // 请求头
    // 'X-Auth-Token': 'xxxx',
    // contentType: "application/x-www-form-urlencoded"
    'Content-Type': 'application/json'
  };
  config.custom = { // 自定义参数,如果局部custom与全局custom有同名属性，则后面的属性会覆盖前面的属性，相当于Object.assign(全局，局部)
    loading: true, // 默认全局请求开启loading
    error: true // 默认全局请求开启错误提示
  };
  config.withCredentials = true; // 跨域请求时携带凭证（cookies）仅H5支持（HBuilderX 2.6.15+）
  return config;
});

/**
* 请求拦截器
* @param {Object} config 发送请求的配置数据
*/
http.interceptors.request.use(config => {
  config.custom.loading && uni.showLoading({ title: '加载中', mask: true }); // 请求配置中的custom自定义参数中loading为true则显示loading
  getToken() && (config.header.token = getToken()); // 有token则在请求头中携带token
  getCookie() && (config.header.cookie = getCookie()); // 有cookie则在请求头中携带cookie，h5中浏览器默认携带cookie，此方法不生效，小程序中需手动携带cookie
  return config;
}, err => {
  showToast(err);
  uni.hideLoading();
  return Promise.reject(err);
});

/**
* 响应拦截器
* @param {Object} res 请求返回的数据
*/
http.interceptors.response.use(async res => {
  let data = res.hasOwnProperty('data') ? res.data : res.hasOwnProperty('Data') ? res.Data : null; // eslint-disable-line
  let code = data.hasOwnProperty('code') ? data.code : data.hasOwnProperty('Code') ? data.Code : null; // eslint-disable-line
  saveCookie(res.header['set-cookie'] || res.header['Set-Cookie']); // 手动种cookie，h5中浏览器自动种cookie，小程序中需手动中cookie
  try {
    return await handleCode({ data, code, res });
  } catch (err) {
    uni.hideLoading();
    res.config.custom.error && showToast(err.msg);
    return Promise.reject(err);
  }
}, err => {
  return Promise.reject(err);
});

/**
 * 处理 http状态码
 * @param {object} o
 * @param {object} o.data 请求返回的数据
 * @param {string|number} o.code http状态码
 * @param {object} o.res 本次请求的配置和返回数据
 * @return {object|Promise<reject>}
 */
function handleCode({ data, code, res }) {
  const STATUS = {
    '0'() { // 请求成功
      return data;
    }
  };
  uni.hideLoading();
  return STATUS[code] ? STATUS[code]() : Promise.reject(data, res); // 有状态码但不在这个封装的配置里，就直接进入 `fail`
}

/**
 * 获取 `localStorage` 中的 `cookie`
 * @return {string} cookie字符串
 */
function getCookie() {
  return uni.getStorageSync('cookie');
}

/**
 * 保存 `cookie` 到  `localStorage`
 * @param {string} cookie cookie字符串
 * @return {void}
 */
function saveCookie(cookie) {
  cookie && uni.setStorageSync('cookie', cookie);
}

/**
 * 获取 `localStorage` 中的 `token`
 * @return {string} token字符串
 */
function getToken() {
  return uni.getStorageSync('token');
}

/**
* 显示消息提示框
* @param {String} msg
* @return {void}
*/
function showToast(msg) {
  return uni.showToast({
    title: msg,
    icon: 'none',
    duration: 2000
  });
}

export { http };
